using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace GameCore
{
    /// <summary>
    /// 界面打开操作模式
    /// </summary>
    public enum UIMode
    {
        /// <summary>
        /// 对当前界面不做处理, 但是能入UI栈
        /// </summary>
        None,
        /// <summary>
        /// 关闭当前界面, 并打开新的界面
        /// </summary>
        CloseCurrUI,
        /// <summary>
        /// 只隐藏当前界面, 然后打开新的界面
        /// </summary>
        HideCurrUI,
        /// <summary>
        /// 不入UI栈
        /// </summary>
        EmptyStack,
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    public class UIBase : MonoBehaviour, IUserInterface
    {
        public Delegate onBack;

        public void ShowUI(Delegate onBack = null, params object[] pars)
        {
            gameObject.SetActive(true);
            transform.SetAsLastSibling();
            if (onBack != null)
                this.onBack = onBack;
            OnShowUI(pars);
        }

        public virtual void HideUI(bool isBack = true, params object[] pars)
        {
            gameObject.SetActive(false);
            if (isBack & onBack != null)
            {
                onBack?.DynamicInvoke(pars);
                onBack = null;
            }
        }

        public virtual void OnShowUI(params object[] pars) { }
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class UIBase<T> : UIBase where T : UIBase<T>
    {
        public static T I => Global.UI.GetFormOrCreate<T>();

        public static async void GetInstanceAsync(Action<T> onComplete)
        {
            var form = await Global.UI.GetFormOrCreateAsync<T>();
            onComplete(form);
        }

        public static T Show(UIMode openMode = UIMode.CloseCurrUI, params object[] pars)
            => Global.UI.OpenFormAsync<T>(null, openMode, false, pars).GetAwaiter().GetResult();

        public static T Show(Delegate onBack, UIMode openMode = UIMode.CloseCurrUI, params object[] pars)
            => Global.UI.OpenFormAsync<T>(onBack, openMode, false, pars).GetAwaiter().GetResult();

        public static async UniTask<T> ShowAsync(UIMode openMode = UIMode.CloseCurrUI, bool isAsync = true, params object[] pars)
            => await Global.UI.OpenFormAsync<T>(null, openMode, isAsync, pars);

        public static async UniTask<T> ShowAsync(Delegate onBack, UIMode openMode = UIMode.CloseCurrUI, bool isAsync = true, params object[] pars)
            => await Global.UI.OpenFormAsync<T>(onBack, openMode, isAsync, pars);

        public static T Show(Action onBack, UIMode openMode = UIMode.CloseCurrUI, params object[] pars)
            => Global.UI.OpenFormAsync<T>(onBack, openMode, false, pars).GetAwaiter().GetResult();

        public static async UniTask<T> ShowAsync(Action onBack, UIMode openMode = UIMode.CloseCurrUI, bool isAsync = true, params object[] pars)
            => await Global.UI.OpenFormAsync<T>(onBack, openMode, isAsync, pars);

        public static void Hide(bool isBack = true, bool navigation = true, params object[] pars)
            => Global.UI.CloseForm<T>(isBack, navigation, pars);
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class UIBase<T, Item> : UIBase<T> where T : UIBase<T, Item>
    {
        public Item item;
        public Transform itemRoot;
        public List<Item> items = new();
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class UIBase<T, Item1, Item2> : UIBase<T> where T : UIBase<T, Item1, Item2>
    {
        public Item1 item_1;
        public Item2 item_2;
        public Transform[] itemRoots;
        public List<Item1> item1List = new();
        public List<Item2> item2List = new();
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class UIBase1<T, Item> : UIBase<T> where T : UIBase1<T, Item>
    {
        public Item[] item;
        public Transform[] itemRoot;
        public List<Item>[] items = new List<Item>[0];
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class NetworkOneUIBase<T> : UIBase<T> where T : NetworkOneUIBase<T>
    {
        public virtual void Awake()
        {
            Global.Network.AddRpcOne(this);
        }

        public virtual void OnDestroy()
        {
            Global.Network.RemoveRpcOne(this);
        }
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class NetworkTwoUIBase<T> : UIBase<T> where T : NetworkTwoUIBase<T>
    {
        public virtual void Awake()
        {
            Global.Network.AddRpcTwo(this);
        }

        public virtual void OnDestroy()
        {
            Global.Network.RemoveRpcTwo(this);
        }
    }

    /// <summary>
    /// UI界面基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class NetworkAllUIBase<T> : UIBase<T> where T : NetworkAllUIBase<T>
    {
        public virtual void Awake()
        {
            Global.Network.AddRpc(-1, this);
        }

        public virtual void OnDestroy()
        {
            Global.Network.RemoveRpc(-1, this);
        }
    }

    public class UIFormBase : UIBase { }
    public class UIFormBase<T> : UIBase<T> where T : UIFormBase<T> { }
    public class UIFormBase<T, Item> : UIBase<T, Item> where T : UIFormBase<T, Item> { }
    public class UIFormBase1<T, Item> : UIBase1<T, Item> where T : UIFormBase1<T, Item> { }
}